`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:58:34 11/29/2007 
// Design Name: 
// Module Name:    top 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module top(
	input CLK_50MHZ,
	input BTN_NORTH,
	input BTN_EAST,
	input BTN_SOUTH,
	input BTN_WEST,
	input ROT_CENTER,
	input[3:0] SW,
    input PS2_CLK,
    input PS2_DATA,
	output VGA_RED,
	output VGA_GREEN,
	output VGA_BLUE,
	output VGA_HSYNC,
	output VGA_VSYNC,
	inout FX2_CLKIN,
	inout FX2_CLKOUT,
	inout FX2_CLKIO,
	inout[34:1] FX2_IO,
	input[38:35] FX2_IP,
	inout FX2_IO39,
	input FX2_IP40
	);
	
    //DSUB Interconnect
    wire[7:0] dsub_out;
    wire dsub_vsyncb;
    wire dsub_hsyncb;
    
    //DSUB Output Assigns
	assign VGA_RED = SW[3] ? dsub_out[5] : dsub_out[4];
	assign VGA_GREEN = SW[3] ? dsub_out[3] : dsub_out[2];
	assign VGA_BLUE = SW[3] ? dsub_out[1] : dsub_out[0];
	assign VGA_VSYNC = dsub_vsyncb;
	assign VGA_HSYNC = dsub_hsyncb;
    
	//VGA Interconnect
	wire vga_clk;
	wire vga_rst;
	wire[15:0] vga_mem;
	wire[17:0] vga_addr;
	wire vga_read;
	wire[7:0] vga_out;
	wire vga_hsyncb;
	wire vga_vsyncb;
	
	//Clock divider to 25MHz
	reg clk;
	always @ (posedge CLK_50MHZ) clk <= ~clk;
	
	//EPROM Inputs
	wire sys_eprom_done;
	wire[7:0] sys_eprom_out;
	assign sys_eprom_out = {/*FX2_IO[33],FX2_IP[35],FX2_IP[37],FX2_IO39*/2'b0,FX2_IP[38],FX2_IP40,FX2_IO[33],FX2_IP[35],FX2_IP[37],FX2_IP[36]};
	//assign sys_eprom_out = {BTN_SOUTH,BTN_WEST,BTN_NORTH,BTN_EAST,SW[3],SW[2],SW[1],SW[0]},
	//assign sys_eprom_out = {BTN_SOUTH,BTN_WEST,BTN_NORTH,BTN_EAST,SW[3],SW[2],SW[1],SW[0]};
	//assign sys_eprom_out = {BTN_SOUTH,BTN_WEST,BTN_NORTH,BTN_EAST,SW[3],SW[2],SW[1],SW[0]};

	//SRAM IO
	wire[15:0] sys_sram_in; //Data going in TO the SRAM
	wire[15:0] sys_sram_out; //Data coming out FROM the SRAM
	wire[15:0] sys_sram_in_tristate;
	wire[15:0] sys_sram_out_tristate;
	assign {/*FX2_IO[32],FX2_IO[30],FX2_IO[28]*//*io_high,*/FX2_CLKOUT,FX2_IO[26],FX2_IO[24],FX2_IO[22],FX2_IO[20],FX2_IO[18],FX2_IO[16],FX2_IO[14],FX2_IO[12],FX2_IO[10],FX2_IO[08],FX2_IO[06],FX2_IO[04],FX2_IO[02]} = sys_sram_in_tristate;
	assign sys_sram_in_tristate = ~sys_eprom_done ? sys_sram_in : 16'bZZZZZZZZZZZZZZZZ;
	assign sys_sram_out_tristate = sys_eprom_done ? {/*FX2_IO[32],FX2_IO[30],FX2_IO[28]*//*io_high,*/FX2_CLKOUT,FX2_IO[26],FX2_IO[24],FX2_IO[22],FX2_IO[20],FX2_IO[18],FX2_IO[16],FX2_IO[14],FX2_IO[12],FX2_IO[10],FX2_IO[08],FX2_IO[06],FX2_IO[04],FX2_IO[02]} : 16'bZZZZZZZZZZZZZZZZ;
	assign sys_sram_out = sys_sram_out_tristate;
	
	//CPU Interconnect
	wire sys_cpu_clk;
	wire sys_cpu_rstb;
	wire sys_cpu_vsyncb;
	wire sys_cpu_sram_readb;
	wire sys_cpu_sram_writeb;
	wire[17:0] sys_cpu_sram_addr;
	wire[15:0] sys_cpu_sram_in;
	wire[15:0] sys_cpu_sram_out;
	wire sys_cpu_ps2_clk;
	wire sys_cpu_ps2_data;
    wire sys_cpu_regfile_re;
    wire sys_cpu_regfile_we;
    wire[15:0] sys_cpu_regfile_in;
    wire[15:0] sys_cpu_regfile_out;
    wire[3:0] sys_cpu_regfile_addr;
	
    //PS/2 Inputs
    wire sys_ps2_clk;
	wire sys_ps2_data;
    assign sys_ps2_clk = PS2_CLK;
	assign sys_ps2_data = PS2_DATA;
    
	//Unconnected syscontrol signals
	wire sys_sram_oeb;
	
SysControl sys_control(
	.CLK (clk),
	.RESET (ROT_CENTER), 
	.EPROM_OUT (sys_eprom_out),
	.EPROM_DONE (sys_eprom_done),
	.SRAM_WEB (FX2_CLKIO),
	.SRAM_BLEB (FX2_IO39),
	.SRAM_BHEB (FX2_IO[34]), 
	.SRAM_OEB (sys_sram_oeb),
	.SRAM_IN (sys_sram_in),
	.SRAM_OUT (sys_sram_out),
	.MEM_ADDR ({FX2_IO[32],FX2_IO[30],FX2_IO[28],FX2_IO[31],FX2_IO[29],FX2_IO[27],FX2_IO[25],FX2_IO[23],FX2_IO[21],FX2_IO[19],FX2_IO[17],FX2_IO[15],FX2_IO[13],FX2_IO[11],FX2_IO[09],FX2_IO[07],FX2_IO[05],FX2_IO[03],FX2_IO[01]}),
	.DSUB_OUT (dsub_out),
    .DSUB_VSYNCB (dsub_vsyncb),
    .DSUB_HSYNCB (dsub_hsyncb),
    .VGA_CLK (vga_clk),
	.VGA_RST (vga_rst),
	.VGA_MEM (vga_mem),
	.VGA_ADDR (vga_addr),
	.VGA_READ (vga_read),
    .VGA_OUT (vga_out),
	.VGA_VSYNCB (vga_vsyncb),
    .VGA_HSYNCB (vga_hsyncb),
	.PS2_CLK (sys_ps2_clk),
	.PS2_DATA (sys_ps2_data),
	.CPU_CLK (sys_cpu_clk),
	.CPU_RSTB (sys_cpu_rstb),
	.CPU_VSYNCB (sys_cpu_vsyncb),
	.CPU_SRAM_READB (sys_cpu_sram_readb),
	.CPU_SRAM_WRITEB (sys_cpu_sram_writeb),
	.CPU_SRAM_ADDR (sys_cpu_sram_addr),
	.CPU_SRAM_IN (sys_cpu_sram_in),
	.CPU_SRAM_OUT (sys_cpu_sram_out),
	.CPU_PS2_CLK (sys_cpu_ps2_clk),
	.CPU_PS2_DATA (sys_cpu_ps2_data),
	.TEST_PATTERN (vga_addr)
);
	
VGA vga(
	.CLK (vga_clk),
	.RST (vga_rst),
	.MEM (vga_mem),
	.ADDR (vga_addr),
	.READ (vga_read),
	.OUT (vga_out),
	.VSYNC_OUTB (vga_vsyncb),
	.HSYNC_OUTB (vga_hsyncb)
);

CPU cpu(
	.clk (sys_cpu_clk),
	.reset (sys_cpu_rstb),
	.vsync_n (sys_cpu_vsyncb),
	.rd (sys_cpu_sram_readb),
	.wr (sys_cpu_sram_writeb),
	.addrOut (sys_cpu_sram_addr),
	.dOut (sys_cpu_sram_in),
	.dIn (sys_cpu_sram_out),
	.ps2_clk (sys_cpu_ps2_clk),
	.ps2_data (sys_cpu_ps2_data),
    .RE (sys_cpu_regfile_re),
    .WE (sys_cpu_regfile_we),
    .D (sys_cpu_regfile_in),
    .Q (sys_cpu_regfile_out),
    .A (sys_cpu_regfile_addr)
);

BlockRam reg_file(
    .CLK (sys_cpu_clk),
    .RESET (sys_cpu_rst),
    .RE (sys_cpu_read),
    .WE (sys_cpu_sram_writeb),
    .D (sys_cpu_regfile_in),
    .Q (sys_cpu_regfile_out),
    .A (sys_cpu_regfile_addr)
);

endmodule
